Skip to content

feat: add standalone ccip-server Docker image and workflow#7565

Merged
paulbalaji merged 22 commits intomainfrom
pbio/ccip-server-dockerfile
Dec 22, 2025
Merged

feat: add standalone ccip-server Docker image and workflow#7565
paulbalaji merged 22 commits intomainfrom
pbio/ccip-server-dockerfile

Conversation

@paulbalaji
Copy link
Collaborator

@paulbalaji paulbalaji commented Dec 8, 2025

Summary

  • Add standalone Docker image for ccip-server (Offchain Lookup Server)
  • Achieves 75% image size reduction vs monorepo (1.64 GB vs 6.45 GB)
  • Add GitHub Actions workflow to build and push to GCR
  • Update helm chart to use standalone image by default

Image Size Comparison

Image Size vs Monorepo (yarn) vs Monorepo (pnpm)
hyperlane-monorepo (yarn) 8.69 GB - -
hyperlane-monorepo (pnpm) 6.45 GB 25.8% smaller -
hyperlane-offchain-lookup-server (standalone) 1.64 GB 81.1% smaller 74.6% smaller

Approach

Uses a multi-stage Docker build with pnpm deploy --legacy --prod to create a standalone deployment with all dependencies resolved (no symlinks). The standalone image includes:

  • Built TypeScript output (dist/)
  • Prisma generated client with native binaries
  • All production dependencies (resolved from pnpm symlinks)

Why not smaller? ncc bundling would produce a much smaller image (~233MB) but Prisma 6 requires native query engine binaries that cannot be bundled. The pnpm deploy approach ensures Prisma compatibility.

Future optimization: Once we upgrade to Node 24, we can upgrade to Prisma 7 which supports ncc bundling. This would reduce the image size to ~300MB (similar to the rebalancer standalone image).

Changes

  • typescript/ccip-server/Dockerfile - Multi-stage Docker build with pnpm deploy
  • typescript/ccip-server/package.json - Add dist to files field for pnpm deploy
  • .github/workflows/ccip-server-docker.yml - CI workflow for building/pushing to GCR
  • typescript/infra/helm/offchain-lookup-server/values.yaml - Use standalone image by default
  • typescript/infra/helm/offchain-lookup-server/values-mainnet.yaml - Use standalone image
  • typescript/infra/helm/offchain-lookup-server/values-testnet.yaml - Use standalone image
  • typescript/infra/helm/offchain-lookup-server/templates/deployment.yaml - Use image CMD for standalone

Stacked on #7545

Test plan

  • Docker build succeeds in CI
  • Server starts correctly with Prisma 6
  • Helm chart updated to use standalone image

🐳 Standalone Image Initiative

This PR is part of a wider effort to migrate TypeScript workloads from the 6.39 GB monorepo image to lightweight standalone images:

PR Workload Pods Nodes Standalone Size Reduction
#7545 Rebalancer 11 7 227 MB 28x
#7565 Offchain Lookup Server 1 1 1.64 GB 4x
#7653 Warp Monitor 181 19 227 MB 28x
Total - 193 20* - -

*20 unique nodes (some overlap between workloads)

Total Infrastructure Savings

  • ~121 GB node disk freed across the cluster
  • Before: 20 nodes × 6.45 GB = 129 GB cached monorepo images
  • After: ~8 GB total standalone images
  • 28x faster pod startup for most workloads
  • Reduced GCR costs from smaller storage and less transfer

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Added an automated CI/CD workflow to build and push multi‑platform CCIP Server images with metadata tagging and optional PR comments.
    • Added a bundling task to the build system.
    • Improved Docker multi‑stage builds, added a placeholder DATABASE_URL during build, and included dist in published package files.
    • Added a documentation note in the Prisma schema.
  • Deployments

    • Updated Helm values to use a dedicated offchain‑lookup‑server image, rely on the image's default startup, and fetch DATABASE_URL via secrets.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Dec 8, 2025

⚠️ No Changeset found

Latest commit: c93d02e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from 4b48339 to 448d9c6 Compare December 8, 2025 18:39
@hyper-gonk
Copy link
Contributor

hyper-gonk bot commented Dec 9, 2025

🔍 Offchain Lookup Server Docker Image Built Successfully

Image Tags:

gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server:pr-7565
gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server:8d0411a-20251209-111249

@hyperlane-xyz hyperlane-xyz deleted a comment from hyper-gonk bot Dec 9, 2025
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch 3 times, most recently from 87d2885 to bcf846e Compare December 15, 2025 16:42
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch 2 times, most recently from 8345189 to c66ec43 Compare December 15, 2025 16:49
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch 2 times, most recently from ccd7788 to 645ac6e Compare December 15, 2025 16:52
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from c66ec43 to 49d3da8 Compare December 15, 2025 16:52
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from 645ac6e to 8adce63 Compare December 15, 2025 17:01
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch 2 times, most recently from 71d681e to 1aa8236 Compare December 15, 2025 17:05
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from b1fb394 to c30ec76 Compare December 15, 2025 17:09
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch 3 times, most recently from 109ddb5 to a55452e Compare December 15, 2025 17:24
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from c17a86b to 3d04d24 Compare December 15, 2025 18:58
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from 0f2e8db to 7e22548 Compare December 15, 2025 19:03
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from 3d04d24 to 97bcf20 Compare December 15, 2025 19:25
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from 7e22548 to 5126b33 Compare December 15, 2025 19:25
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from efdc189 to 2ea5775 Compare December 17, 2025 12:40
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from 606b58a to 20f31cb Compare December 17, 2025 12:40
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from 2ea5775 to 0717db3 Compare December 17, 2025 12:45
@paulbalaji paulbalaji force-pushed the pbio/ccip-server-dockerfile branch from 20f31cb to 51006a1 Compare December 17, 2025 12:45
@paulbalaji paulbalaji force-pushed the pbio/rebalancer-dockerfile branch from 0717db3 to e717abe Compare December 17, 2025 12:52
@paulbalaji paulbalaji reopened this Dec 18, 2025
@github-project-automation github-project-automation bot moved this from Done to Sprint in Hyperlane Tasks Dec 18, 2025
@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (20d5989) to head (c93d02e).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #7565       +/-   ##
==========================================
- Coverage   77.02%       0   -77.03%     
==========================================
  Files         117       0      -117     
  Lines        2651       0     -2651     
  Branches      244       0      -244     
==========================================
- Hits         2042       0     -2042     
+ Misses        593       0      -593     
+ Partials       16       0       -16     
Flag Coverage Δ
solidity ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
core ∅ <ø> (∅)
hooks ∅ <ø> (∅)
isms ∅ <ø> (∅)
token ∅ <ø> (∅)
middlewares ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/ccip-server-docker.yml (1)

105-115: Build and push step looks good, though that hardcoded project ID could live in a variable.

The Depot project ID on line 109 works fine, but considerin' movin' it to a secret or repository variable would make it easier if you ever need to change it. Not urgent though, just a "nice to have" for tidiness.

🔎 Optional: Use a variable for project ID
       - name: Build and push
         id: build
         uses: depot/build-push-action@v1
         with:
-          project: 3cpjhx94qv
+          project: ${{ vars.DEPOT_PROJECT_ID }}
           context: ./
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20d5989 and 4b41dc7.

📒 Files selected for processing (10)
  • .github/workflows/ccip-server-docker.yml
  • Dockerfile
  • turbo.json
  • typescript/ccip-server/Dockerfile
  • typescript/ccip-server/package.json
  • typescript/ccip-server/prisma/schema.prisma
  • typescript/infra/helm/offchain-lookup-server/templates/deployment.yaml
  • typescript/infra/helm/offchain-lookup-server/values-mainnet.yaml
  • typescript/infra/helm/offchain-lookup-server/values-testnet.yaml
  • typescript/infra/helm/offchain-lookup-server/values.yaml
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-13T16:53:55.163Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6891
File: typescript/infra/config/environments/mainnet3/funding.ts:22-22
Timestamp: 2025-08-13T16:53:55.163Z
Learning: In Hyperlane mainnet3 configs, funding.ts uses 'gcr.io/abacus-labs-dev/hyperlane-monorepo' docker image while agent.ts uses 'gcr.io/abacus-labs-dev/hyperlane-agent' docker image. These are different images with independent tag cycles, so tag consistency across them is not expected.

Applied to files:

  • typescript/infra/helm/offchain-lookup-server/values-mainnet.yaml
  • typescript/infra/helm/offchain-lookup-server/values.yaml
  • typescript/infra/helm/offchain-lookup-server/values-testnet.yaml
📚 Learning: 2025-08-26T13:45:52.227Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6943
File: rust/main/config/testnet_config.json:34-35
Timestamp: 2025-08-26T13:45:52.227Z
Learning: Skip reviewing mainnet_config.json and testnet_config.json configuration files in typescript/infra/config/ and rust/main/config/ directories as requested by paulbalaji to reduce review noise.

Applied to files:

  • typescript/infra/helm/offchain-lookup-server/values-testnet.yaml
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Most deployments are config-driven; check `typescript/infra/config/` for deployment configuration examples

Applied to files:

  • typescript/ccip-server/Dockerfile
  • typescript/infra/helm/offchain-lookup-server/templates/deployment.yaml
🪛 Checkov (3.2.334)
Dockerfile

[medium] 46-47: Basic Auth Credentials

(CKV_SECRET_4)

typescript/ccip-server/Dockerfile

[medium] 43-44: Basic Auth Credentials

(CKV_SECRET_4)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (60)
  • GitHub Check: cli-evm-e2e-matrix (warp-read)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-3)
  • GitHub Check: cli-evm-e2e-matrix (relay)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-send)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-init)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-4)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-5)
  • GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
  • GitHub Check: cli-evm-e2e-matrix (status)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
  • GitHub Check: cli-evm-e2e-matrix (core-init)
  • GitHub Check: cli-evm-e2e-matrix (core-apply)
  • GitHub Check: cli-evm-e2e-matrix (core-check)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
  • GitHub Check: cli-evm-e2e-matrix (core-read)
  • GitHub Check: cli-evm-e2e-matrix (core-deploy)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: env-test-matrix (testnet4, sepolia, core)
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
  • GitHub Check: env-test-matrix (mainnet3, optimism, core)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, core)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
  • GitHub Check: cli-cosmos-e2e-matrix (core-check)
  • GitHub Check: cli-radix-e2e-matrix (core-apply)
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
  • GitHub Check: env-test-matrix (mainnet3, optimism, igp)
  • GitHub Check: cli-cosmos-e2e-matrix (core-read)
  • GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
  • GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
  • GitHub Check: cli-radix-e2e-matrix (warp-deploy)
  • GitHub Check: cli-radix-e2e-matrix (core-deploy)
  • GitHub Check: cli-install-test-run
  • GitHub Check: cosmos-sdk-e2e-run
  • GitHub Check: cli-cosmos-e2e-matrix (warp-read)
  • GitHub Check: cli-cosmos-e2e-matrix (core-apply)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: aleo-sdk-e2e-run
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
  • GitHub Check: pnpm-test-run
  • GitHub Check: infra-test
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: e2e-matrix (evm)
  • GitHub Check: lint-rs
  • GitHub Check: lander-coverage
  • GitHub Check: test-rs
🔇 Additional comments (21)
typescript/ccip-server/package.json (1)

8-11: Including built output in deployment artifacts - looks solid.

Adding "dist" to the files array ensures pnpm deploy picks up your compiled TypeScript output. This lines up nicely with the multi-stage build approach in the Dockerfile.

Dockerfile (1)

45-46: Placeholder DATABASE_URL for Prisma - proper approach.

Setting a dummy DATABASE_URL here is the right move since prisma generate needs it during the build but doesn't actually connect to a database. The real DATABASE_URL comes from Kubernetes secrets at runtime (as seen in values.yaml).

Note: Static analysis flagged this as a credential issue, but that's a false positive - it's just a placeholder.

turbo.json (1)

30-33: Bundle task addition looks fine.

The new bundle task with its dependency on ^build and wildcard output pattern should work well for the broader packaging strategy mentioned in the PR objectives.

typescript/infra/helm/offchain-lookup-server/templates/deployment.yaml (1)

1-49: Cleaner deployment with image-defined startup.

The removal of explicit command and args (letting the image use its built-in ENTRYPOINT/CMD) makes sense for a standalone image. Keeps things simpler and more portable while maintaining all the important bits like health checks and environment config.

typescript/ccip-server/prisma/schema.prisma (1)

9-9: Documentation clarifies DATABASE_URL usage - helpful addition.

This comment nicely explains the distinction between build-time (prisma generate needs it) and runtime (actual connection) usage of DATABASE_URL. Good for future folks who might wonder why there's a placeholder in the Dockerfile.

typescript/infra/helm/offchain-lookup-server/values.yaml (2)

5-9: Image reference migration to standalone image - clean.

Switching from the monorepo image to the dedicated offchain-lookup-server image is well-executed. The artifact URL guidance in the comments is updated to match, which will help folks find the right images.


11-15: DATABASE_URL properly secured via secrets.

Adding DATABASE_URL to secret_envs ensures it's fetched from Google Secret Manager at runtime rather than being baked into the image or committed to the config. That's the way to do it.

typescript/infra/helm/offchain-lookup-server/values-mainnet.yaml (1)

5-9: Mainnet image migration looks good.

Image reference updated to the standalone offchain-lookup-server repository. The tag matches across environments (testnet/mainnet), which makes sense for a coordinated rollout of the new standalone image.

typescript/infra/helm/offchain-lookup-server/values-testnet.yaml (1)

5-9: Testnet image migration mirrors mainnet - consistent.

Same clean migration to the standalone image as mainnet, with tag consistency maintained across all environments. Testnet-specific configuration (sandbox URLs, different secrets prefix) is properly preserved.

typescript/ccip-server/Dockerfile (5)

1-12: Lookin' good, like a fresh layer of mud!

The build stage setup is solid - proper base image, necessary build dependencies, and Foundry installation for Solidity builds. Clearin' out those apt lists after is a nice touch for keepin' the image size down in this here swamp.


14-22: Nice layer orderin' for that cache optimization, donkey would be proud.

Copyin' the package.json first for corepack, then the lockfile and workspace config - that's the way to do it. Keeps the install layer cached when only source files change.


24-48: Selective package copies, very onion-like layers - I approve.

The static analysis tool got a bit confused about line 43's DATABASE_URL, but that's just a placeholder for build-time prisma generate. The real connection string comes at runtime, so no swamp creatures sneakin' into your secrets here.

Good practice copyin' the prisma schema before install so the postinstall hook works proper-like.


50-64: All the source copies in their proper place, after the install layer.

This keeps the dependency installation cached when only source files change. Smart like Lord Farquaad thinks he is, but actually works.


81-105: A nice slim production image, like a proper ogre's diet.

Minimal dependencies, just ca-certificates for TLS. The runner stage is clean and focused. Good that you're keepin' the prisma schema around for migrations.

Port 9090 looks like it's for metrics or health checks alongside the main 3000 - might be worth a quick comment in the Dockerfile for future travelers through this swamp.

.github/workflows/ccip-server-docker.yml (7)

7-21: Some packages in the Dockerfile aren't in your path triggers, might want to check that's intentional.

The Dockerfile copies these additional packages that aren't in the workflow triggers:

  • typescript/cosmos-sdk/**
  • typescript/cosmos-types/**
  • typescript/radix-sdk/**
  • typescript/tsconfig/**
  • typescript/eslint-config/**
  • solidity/**
  • solhint-plugin/**
  • starknet/**

If changes to those packages could affect the ccip-server build, you might want 'em in the path filters. Otherwise, changes there won't trigger a rebuild, and you'd pick 'em up on the next ccip-server change. Not necessarily wrong, just make sure that's what you're after.


29-31: Concurrency settings look right, no need to keep buildin' old stuff when new commits come in.


33-43: Good pattern for checkin' if secrets exist before runnin' the build.

Keeps forks and external contributors from hittin' brick walls when they don't have access to your GCloud secrets. Smart like a proper swamp dweller.


45-67: Job setup is proper, with the right permissions and full git history for the diff checks later.

The fetch-depth: 0 is needed for that git diff on line 122 to work right. Good thinkin'.


69-84: Tag generation strategy is solid - SHA and date gives you unique, traceable images.

The combination of branch/PR refs plus the SHA-DATE tag is a good approach. You can always find what you're lookin' for in that swamp of images.


86-103: Platform selection logic is clean, arm64 when you need it, amd64 by default.

Depot for the build cachin' should speed things up nicely. The GCR login is standard fare.


117-138: Smart to only comment when there's actual ccip-server changes, not just dependency updates.

The git diff check keeps your PR comments meaningful instead of cluttering every single build. Good restraint there.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
typescript/ccip-server/Dockerfile (1)

81-105: Consider running as a non-root user.

The runner stage currently runs as root, which is a common pattern but not the most secure. For production deployments, runnin' as a non-root user adds a layer of defense.

🔎 Proposed enhancement to add non-root user
 FROM node:20-slim AS runner
 
 WORKDIR /app
 
 RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
     && rm -rf /var/lib/apt/lists/*
 
+# Create non-root user
+RUN groupadd -r nodeapp && useradd -r -g nodeapp nodeapp
+
 # Copy the deployed standalone package
 COPY --from=builder /app ./
 
 # Copy prisma schema for migrations
 COPY --from=builder /hyperlane-monorepo/typescript/ccip-server/prisma ./prisma
 
+# Change ownership to non-root user
+RUN chown -R nodeapp:nodeapp /app
+
+# Switch to non-root user
+USER nodeapp
+
 # Environment variables
 ENV NODE_ENV=production
 ENV LOG_LEVEL=info
 ENV SERVER_PORT=3000
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b41dc7 and 97df123.

📒 Files selected for processing (2)
  • .github/workflows/ccip-server-docker.yml
  • typescript/ccip-server/Dockerfile
🧰 Additional context used
🪛 Checkov (3.2.334)
typescript/ccip-server/Dockerfile

[medium] 43-44: Basic Auth Credentials

(CKV_SECRET_4)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (63)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-read)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-send)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-3)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
  • GitHub Check: cli-evm-e2e-matrix (status)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-init)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
  • GitHub Check: cli-evm-e2e-matrix (core-init)
  • GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
  • GitHub Check: cli-evm-e2e-matrix (core-check)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-5)
  • GitHub Check: cli-evm-e2e-matrix (core-deploy)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-4)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
  • GitHub Check: cli-evm-e2e-matrix (core-read)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
  • GitHub Check: cli-evm-e2e-matrix (core-apply)
  • GitHub Check: cli-evm-e2e-matrix (relay)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
  • GitHub Check: cli-radix-e2e-matrix (core-apply)
  • GitHub Check: cli-cosmos-e2e-matrix (warp-read)
  • GitHub Check: env-test-matrix (testnet4, sepolia, core)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
  • GitHub Check: cli-radix-e2e-matrix (core-deploy)
  • GitHub Check: env-test-matrix (mainnet3, optimism, igp)
  • GitHub Check: cli-radix-e2e-matrix (warp-deploy)
  • GitHub Check: env-test-matrix (mainnet3, optimism, core)
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, core)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
  • GitHub Check: cli-cosmos-e2e-matrix (core-read)
  • GitHub Check: cli-cosmos-e2e-matrix (core-apply)
  • GitHub Check: cli-cosmos-e2e-matrix (core-check)
  • GitHub Check: cli-install-test-run
  • GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
  • GitHub Check: aleo-sdk-e2e-run
  • GitHub Check: pnpm-test-run
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
  • GitHub Check: cosmos-sdk-e2e-run
  • GitHub Check: infra-test
  • GitHub Check: agent-configs (testnet4)
  • GitHub Check: e2e-matrix (evm)
  • GitHub Check: agent-configs (mainnet3)
  • GitHub Check: lint-prettier
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: lander-coverage
  • GitHub Check: lint-rs
  • GitHub Check: test-rs
🔇 Additional comments (10)
typescript/ccip-server/Dockerfile (4)

18-38: Smart layer caching strategy here.

Copyin' the package.json files separately before the source code is a solid move for Docker layer caching. When dependencies don't change, the install layer can be reused, speedin' up subsequent builds considerably.


42-43: Placeholder DATABASE_URL is the right approach here.

Static analysis flagged this as credentials, but that's a false positive. Prisma needs a DATABASE_URL at generate time, even though it doesn't actually connect to anything during the build. The placeholder value is fine, and the real connection string gets provided at runtime through environment variables.


50-67: Build orchestration looks solid.

The turbo build with filtering ensures only the ccip-server and its dependencies get built, which keeps the build focused and efficient.


77-79: Good fix from the previous review.

The explicit build failure when the .prisma directory can't be found will catch the problem before it gets to production, rather than lettin' an incomplete image slip through. Much better than just echoin' a warning.

.github/workflows/ccip-server-docker.yml (6)

1-23: Workflow triggers and concurrency are well-configured.

The path filters ensure this only runs when ccip-server or the workflow itself changes, which saves CI resources. The concurrency group with cancel-in-progress is smart for PRs where you're pushin' multiple commits quickly.


25-35: Smart pre-check for credentials.

Checkin' for the GCloud service key upfront prevents the build job from runnin' when credentials aren't available, which saves time and makes failures clearer.


37-59: Job setup and checkout look good.

The conditional dependency on check-env, GitHub App token for PR interactions, and proper checkout with submodules are all well-configured for this workflow's needs.


61-77: Tag strategy provides good traceability.

The combination of branch tags, PR tags, and SHA-timestamp tags ensures you can trace any deployed image back to its source commit and build time, which is mighty useful for debuggin' issues in production.


78-96: Build infrastructure is well-configured.

Depot CLI for faster builds and the flexible platform determination give you control over whether to include arm64 without needin' separate workflows. The default of amd64-only keeps PR builds fast.


97-119: Build and PR feedback are solid.

The build configuration correctly uses the root context for the monorepo setup, and the PR comment gives reviewers immediate visibility into what image tags were created. Nice touch!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
typescript/ccip-server/Dockerfile (1)

9-12: Consider using the official Foundry image for better reproducibility.

The curl-pipe-bash works fine, but the official ghcr.io/foundry-rs/foundry image gives you more control over versions and better reproducibility. Pin a specific tag instead of relying on foundryup flags.

🧹 Nitpick comments (1)
typescript/ccip-server/Dockerfile (1)

91-101: Environment and startup look good.

Production defaults are set properly, ports are exposed, and the CMD is straightforward.

🔎 Optional: Add a HEALTHCHECK instruction

Consider addin' a HEALTHCHECK to help container orchestrators know when your server is ready:

 EXPOSE 3000
 EXPOSE 9090
+
+# Optional: Health check (adjust the endpoint as needed)
+HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
+  CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
 
 # Run the ccip-server
 CMD ["node", "dist/server.js"]
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97df123 and 16eab2f.

📒 Files selected for processing (1)
  • typescript/ccip-server/Dockerfile
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-18T22:36:13.376Z
Learnt from: CR
Repo: hyperlane-xyz/hyperlane-monorepo PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-18T22:36:13.376Z
Learning: Most deployments are config-driven; check `typescript/infra/config/` for deployment configuration examples

Applied to files:

  • typescript/ccip-server/Dockerfile
📚 Learning: 2025-11-25T17:10:33.369Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 7410
File: solidity/foundry.toml:8-8
Timestamp: 2025-11-25T17:10:33.369Z
Learning: In the hyperlane-xyz/hyperlane-monorepo repository, when using pnpm (instead of Yarn), Foundry's `allow_paths` in solidity/foundry.toml should be set to `["./node_modules"]` rather than `["../node_modules"]` because pnpm's default node_modules structure places dependencies locally in the workspace subdirectory, not requiring access to the parent directory's node_modules.

Applied to files:

  • typescript/ccip-server/Dockerfile
📚 Learning: 2025-08-13T16:53:55.163Z
Learnt from: paulbalaji
Repo: hyperlane-xyz/hyperlane-monorepo PR: 6891
File: typescript/infra/config/environments/mainnet3/funding.ts:22-22
Timestamp: 2025-08-13T16:53:55.163Z
Learning: In Hyperlane mainnet3 configs, funding.ts uses 'gcr.io/abacus-labs-dev/hyperlane-monorepo' docker image while agent.ts uses 'gcr.io/abacus-labs-dev/hyperlane-agent' docker image. These are different images with independent tag cycles, so tag consistency across them is not expected.

Applied to files:

  • typescript/ccip-server/Dockerfile
🪛 Checkov (3.2.334)
typescript/ccip-server/Dockerfile

[medium] 43-44: Basic Auth Credentials

(CKV_SECRET_4)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (63)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-submitters)
  • GitHub Check: pnpm-test-run
  • GitHub Check: cli-evm-e2e-matrix (warp-read)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-send)
  • GitHub Check: cli-evm-e2e-matrix (core-read)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-5)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-hook-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-init)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-1)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-recovery)
  • GitHub Check: cli-evm-e2e-matrix (warp-rebalancer)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ism-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-4)
  • GitHub Check: cli-evm-e2e-matrix (warp-deploy-2)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-config)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: cli-evm-e2e-matrix (warp-bridge-1)
  • GitHub Check: cli-evm-e2e-matrix (core-init)
  • GitHub Check: cli-evm-e2e-matrix (status)
  • GitHub Check: cli-evm-e2e-matrix (warp-check-3)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-simple-updates)
  • GitHub Check: cli-radix-e2e-matrix (core-deploy)
  • GitHub Check: cli-evm-e2e-matrix (warp-apply-rebalancing-config)
  • GitHub Check: cli-evm-e2e-matrix (core-check)
  • GitHub Check: cli-evm-e2e-matrix (relay)
  • GitHub Check: cli-evm-e2e-matrix (warp-extend-basic)
  • GitHub Check: cli-evm-e2e-matrix (core-deploy)
  • GitHub Check: cli-evm-e2e-matrix (core-apply)
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, igp)
  • GitHub Check: env-test-matrix (testnet4, sepolia, core)
  • GitHub Check: aleo-sdk-e2e-run
  • GitHub Check: env-test-matrix (mainnet3, arbitrum, core)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, igp)
  • GitHub Check: cli-cosmos-e2e-matrix (warp-read)
  • GitHub Check: cli-cosmos-e2e-matrix (core-check)
  • GitHub Check: env-test-matrix (mainnet3, ethereum, core)
  • GitHub Check: env-test-matrix (mainnet3, optimism, core)
  • GitHub Check: cli-cosmos-e2e-matrix (core-deploy)
  • GitHub Check: cli-cosmos-e2e-matrix (core-read)
  • GitHub Check: env-test-matrix (mainnet3, optimism, igp)
  • GitHub Check: cosmos-sdk-e2e-run
  • GitHub Check: cli-cosmos-e2e-matrix (core-apply)
  • GitHub Check: cli-radix-e2e-matrix (warp-deploy)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-ownership-updates)
  • GitHub Check: cli-radix-e2e-matrix (core-apply)
  • GitHub Check: cli-cosmos-e2e-matrix (warp-deploy)
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-apply)
  • GitHub Check: cli-radix-e2e-matrix (warp-apply-route-extension)
  • GitHub Check: cli-install-test-run
  • GitHub Check: cli-cross-chain-e2e-matrix (warp-deploy)
  • GitHub Check: infra-test
  • GitHub Check: agent-configs (mainnet3)
  • GitHub Check: agent-configs (testnet4)
  • GitHub Check: e2e-matrix (evm)
  • GitHub Check: lint-prettier
  • GitHub Check: lander-coverage
  • GitHub Check: lint-rs
  • GitHub Check: test-rs
  • GitHub Check: build-and-push-to-gcr
  • GitHub Check: build-and-push-to-gcr
🔇 Additional comments (15)
typescript/ccip-server/Dockerfile (15)

1-3: Good choice on the base image.

node:20-slim keeps things lean while Node 20 is LTS. The monorepo workdir makes sense for the build context.


5-7: Dependencies look solid.

All the build tools are here and you're cleanin' up after yourself with the apt lists removal. That's how you keep your layers from gettin' too heavy.


14-16: Smart sequencing with corepack.

Copyin' package.json first so corepack can read the packageManager field is the right move. This ensures you're usin' the right package manager version.


18-22: PNPM config and patches properly layered.

Gettin' the lock file, workspace config, and patches in place before the package.json files is good Docker layer hygiene.


24-37: Dependencies are well-organized for layer caching.

Copyin' just the package.json files for all the workspace dependencies before the full source means Docker can cache the install layer better. This list looks comprehensive for what ccip-server needs.


39-40: Prisma schema placement is correct.

Copyin' the schema before install is necessary since the postinstall hooks need it to generate the client. Good sequencing.


42-43: Placeholder DATABASE_URL is appropriate for Prisma.

Prisma's generate needs a valid-lookin' URL format even though it doesn't actually connect during build. The comment makes it clear this is just a placeholder. The static analysis warning here is a false positive.


45-45: Frozen lockfile for reproducible builds.

Using --frozen-lockfile ensures you get the exact dependencies every time. That's the way it should be done.


47-48: Explicit Prisma generate is good practice.

Even though postinstall might handle it, explicitly runnin' the generate step makes the build more predictable and easier to debug.


50-64: Source copying follows good Docker layer practices.

Now that dependencies are installed and cached, copyin' the full source happens in a separate layer. The list matches the package.json files from earlier.


66-67: Turbo build with filter is efficient.

Using turbo with the filter ensures you're only buildin' ccip-server and its dependencies, not the whole monorepo.


69-71: PNPM deploy creates a proper standalone package.

The deploy command with --legacy and --prod flags creates a deployment-ready package without symlinks. The comment about pnpm v10+ compatibility is helpful context.


73-75: Prisma client copy is well-documented.

The custom output path is clearly explained, and copyin' the generated client to dist makes sense since TypeScript won't do it automatically. This addresses the earlier concern about Prisma assets.


77-83: Runner stage is properly minimal.

node:20-slim with just ca-certificates keeps the final image lean. Good separation between build and runtime concerns.


85-89: Artifact copies cover both runtime and migrations.

Copyin' the deployed package plus the schema separately ensures both the app and any runtime migrations have what they need.

paulbalaji and others added 3 commits December 22, 2025 16:57
Use pinned Foundry binaries from solidity/.foundryrc instead of curl|bash
installer for reproducibility. Also removes unnecessary .prisma copy step
since Prisma outputs to custom path (src/generated/prisma/).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
node:20-slim uses dash as /bin/sh which doesn't support pipefail.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Match monorepo behavior - build on all main pushes, path filter only for PRs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@paulbalaji paulbalaji enabled auto-merge December 22, 2025 17:12
@hyper-gonk
Copy link
Contributor

hyper-gonk bot commented Dec 22, 2025

🐳 Monorepo Docker Image Built Successfully

Image Tags:

gcr.io/abacus-labs-dev/hyperlane-monorepo:pr-7565
gcr.io/abacus-labs-dev/hyperlane-monorepo:c93d02e-20251222-171329

@hyper-gonk
Copy link
Contributor

hyper-gonk bot commented Dec 22, 2025

🔍 CCIP Server Docker Image Built Successfully

Image Tags:

gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server:pr-7565
gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server:c93d02e-20251222-171338

@paulbalaji paulbalaji added this pull request to the merge queue Dec 22, 2025
Merged via the queue into main with commit 9ac4470 Dec 22, 2025
87 of 89 checks passed
@paulbalaji paulbalaji deleted the pbio/ccip-server-dockerfile branch December 22, 2025 17:38
@github-project-automation github-project-automation bot moved this from Sprint to Done in Hyperlane Tasks Dec 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants